<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>设备配置管理 - 工业物联网数据采集系统</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <style>
        .config-form {
            background: white;
            border-radius: 10px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.1);
            padding: 30px;
            margin-bottom: 30px;
        }
        
        .protocol-selector {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border-radius: 10px;
            padding: 20px;
            margin-bottom: 30px;
        }
        
        .tag-config-table {
            background: white;
            border-radius: 10px;
            overflow: hidden;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        
        .btn-add-tag {
            background: linear-gradient(45deg, #28a745, #20c997);
            border: none;
            border-radius: 25px;
            padding: 10px 25px;
            color: white;
            font-weight: bold;
        }
        
        .btn-remove-tag {
            background: linear-gradient(45deg, #dc3545, #fd7e14);
            border: none;
            border-radius: 50%;
            width: 35px;
            height: 35px;
            color: white;
        }
        
        .form-control, .form-select {
            border-radius: 8px;
            border: 2px solid #e9ecef;
            transition: all 0.3s ease;
        }
        
        .form-control:focus, .form-select:focus {
            border-color: #667eea;
            box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25);
        }
        
        .test-connection {
            background: linear-gradient(45deg, #17a2b8, #6f42c1);
            border: none;
            border-radius: 25px;
            color: white;
        }
        
        .config-preview {
            background: #f8f9fa;
            border-radius: 10px;
            padding: 20px;
            font-family: monospace;
            font-size: 14px;
            max-height: 400px;
            overflow-y: auto;
        }
    </style>
</head>
<body class="bg-light">
    <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
        <div class="container">
            <a class="navbar-brand" href="/">
                <i class="fas fa-industry me-2"></i>
                工业物联网数据采集系统
            </a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav ms-auto">
                    <li class="nav-item">
                        <a class="nav-link" href="/">
                            <i class="fas fa-home me-1"></i>主控台
                        </a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="/dashboard">
                            <i class="fas fa-chart-line me-1"></i>监控仪表盘
                        </a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="/device-manager">
                            <i class="fas fa-cogs me-1"></i>设备管理
                        </a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link active" href="/device-config">
                            <i class="fas fa-plus-circle me-1"></i>快速配置
                        </a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="/status-test">
                            <i class="fas fa-stethoscope me-1"></i>系统诊断
                        </a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>

    <div class="container-fluid mt-4">
        <div class="row">
            <!-- 左侧配置表单 -->
            <div class="col-lg-8">
                <div class="config-form">
                    <h3 class="mb-4">
                        <i class="fas fa-plus-circle text-primary me-2"></i>
                        设备配置
                    </h3>
                    
                    <form id="deviceConfigForm">
                        <!-- 基本信息 -->
                        <div class="protocol-selector">
                            <h5 class="mb-3">
                                <i class="fas fa-info-circle me-2"></i>
                                基本信息
                            </h5>
                            <div class="row">
                                <div class="col-md-6">
                                    <label class="form-label">设备名称 *</label>
                                    <input type="text" class="form-control" id="deviceName" required>
                                    <div class="form-text text-white-50">唯一标识，建议使用英文和数字</div>
                                </div>
                                <div class="col-md-6">
                                    <label class="form-label">设备描述</label>
                                    <input type="text" class="form-control" id="deviceDescription" placeholder="设备用途说明">
                                </div>
                            </div>
                            <div class="row mt-3">
                                <div class="col-md-6">
                                    <label class="form-label">协议类型 *</label>
                                    <select class="form-select" id="protocolType" required onchange="updateProtocolForm()">
                                        <option value="">请选择协议</option>
                                        <option value="modbus">Modbus TCP/RTU</option>
                                        <option value="s7">西门子 S7</option>
                                        <option value="opcua">OPC UA</option>
                                        <option value="mqtt">MQTT</option>
                                    </select>
                                </div>
                                <div class="col-md-6">
                                    <label class="form-label">轮询间隔 (ms)</label>
                                    <input type="number" class="form-control" id="pollingInterval" value="1000" min="100">
                                </div>
                            </div>
                        </div>

                        <!-- 协议特定配置 -->
                        <div id="protocolConfig">
                            <!-- Modbus配置 -->
                            <div id="modbusConfig" class="protocol-config" style="display: none;">
                                <h5 class="text-primary mb-3">
                                    <i class="fas fa-network-wired me-2"></i>
                                    Modbus 连接配置
                                </h5>
                                <div class="row">
                                    <div class="col-md-4">
                                        <label class="form-label">IP地址 *</label>
                                        <input type="text" class="form-control" id="modbusHost" placeholder="192.168.1.100">
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label">端口</label>
                                        <input type="number" class="form-control" id="modbusPort" value="502">
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label">从站ID</label>
                                        <input type="number" class="form-control" id="modbusSlaveId" value="1" min="1" max="255">
                                    </div>
                                </div>
                                <div class="row mt-3">
                                    <div class="col-md-6">
                                        <label class="form-label">超时时间 (秒)</label>
                                        <input type="number" class="form-control" id="modbusTimeout" value="3" min="1">
                                    </div>
                                    <div class="col-md-6">
                                        <label class="form-label">重试次数</label>
                                        <input type="number" class="form-control" id="modbusRetries" value="3" min="0">
                                    </div>
                                </div>
                            </div>

                            <!-- S7配置 -->
                            <div id="s7Config" class="protocol-config" style="display: none;">
                                <h5 class="text-success mb-3">
                                    <i class="fas fa-microchip me-2"></i>
                                    西门子 S7 连接配置
                                </h5>
                                <div class="row">
                                    <div class="col-md-4">
                                        <label class="form-label">IP地址 *</label>
                                        <input type="text" class="form-control" id="s7Host" placeholder="192.168.1.100">
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label">机架号</label>
                                        <input type="number" class="form-control" id="s7Rack" value="0" min="0">
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label">插槽号</label>
                                        <input type="number" class="form-control" id="s7Slot" value="1" min="0">
                                    </div>
                                </div>
                            </div>

                            <!-- OPC UA配置 -->
                            <div id="opcuaConfig" class="protocol-config" style="display: none;">
                                <h5 class="text-info mb-3">
                                    <i class="fas fa-server me-2"></i>
                                    OPC UA 连接配置
                                </h5>
                                <div class="row">
                                    <div class="col-md-8">
                                        <label class="form-label">服务器端点 *</label>
                                        <input type="text" class="form-control" id="opcuaEndpoint" 
                                               placeholder="opc.tcp://127.0.0.1:49320" required>
                                        <div class="form-text">必填：OPC UA服务器完整URL地址</div>
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label">安全策略</label>
                                        <select class="form-select" id="opcuaSecurity">
                                            <option value="None">无安全</option>
                                            <option value="Basic128Rsa15">Basic128Rsa15</option>
                                            <option value="Basic256">Basic256</option>
                                        </select>
                                    </div>
                                </div>
                                <div class="row mt-3">
                                    <div class="col-md-6">
                                        <label class="form-label">用户名</label>
                                        <input type="text" class="form-control" id="opcuaUsername">
                                    </div>
                                    <div class="col-md-6">
                                        <label class="form-label">密码</label>
                                        <input type="password" class="form-control" id="opcuaPassword">
                                    </div>
                                </div>
                                <div class="mt-3">
                                    <button type="button" class="btn btn-outline-info" onclick="browseOpcuaNodes()">
                                        <i class="fas fa-search me-2"></i>
                                        浏览服务器节点
                                    </button>
                                    <div id="opcuaBrowsingStatus" class="mt-2"></div>
                                </div>
                            </div>

                            <!-- MQTT配置 -->
                            <div id="mqttConfig" class="protocol-config" style="display: none;">
                                <h5 class="text-warning mb-3">
                                    <i class="fas fa-comments me-2"></i>
                                    MQTT 连接配置
                                </h5>
                                <div class="row">
                                    <div class="col-md-4">
                                        <label class="form-label">Broker地址 *</label>
                                        <input type="text" class="form-control" id="mqttHost" placeholder="192.168.1.100">
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label">端口</label>
                                        <input type="number" class="form-control" id="mqttPort" value="1883">
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label">客户端ID</label>
                                        <input type="text" class="form-control" id="mqttClientId" placeholder="自动生成">
                                    </div>
                                </div>
                                <div class="row mt-3">
                                    <div class="col-md-6">
                                        <label class="form-label">用户名</label>
                                        <input type="text" class="form-control" id="mqttUsername">
                                    </div>
                                    <div class="col-md-6">
                                        <label class="form-label">密码</label>
                                        <input type="password" class="form-control" id="mqttPassword">
                                    </div>
                                </div>
                                <div class="mt-3">
                                    <label class="form-label">订阅主题 (每行一个)</label>
                                    <textarea class="form-control" id="mqttTopics" rows="3" 
                                              placeholder="sensor/temperature&#10;sensor/pressure&#10;device/status"></textarea>
                                </div>
                            </div>
                        </div>

                        <!-- 连接测试 -->
                        <div class="d-flex gap-2 mt-4">
                            <button type="button" class="btn test-connection" onclick="testConnection()">
                                <i class="fas fa-plug me-2"></i>
                                测试连接
                            </button>
                            <div id="connectionStatus" class="align-self-center"></div>
                        </div>
                    </form>
                </div>

                <!-- 数据点配置 -->
                <div class="tag-config-table">
                    <div class="table-responsive">
                        <table class="table table-hover mb-0">
                            <thead class="bg-primary text-white">
                                <tr>
                                    <th>标签名称</th>
                                    <th id="addressHeader">地址/节点ID</th>
                                    <th>数据类型</th>
                                    <th>访问权限</th>
                                    <th>描述</th>
                                    <th>单位</th>
                                    <th>操作</th>
                                </tr>
                            </thead>
                            <tbody id="tagsTableBody">
                                <tr>
                                    <td colspan="7" class="text-center text-muted py-4">
                                        <i class="fas fa-database fa-2x mb-2"></i>
                                        <p class="mb-0">暂无数据点配置</p>
                                        <small>请先配置设备连接信息</small>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                    <div class="p-3 bg-light">
                        <button type="button" class="btn btn-add-tag" onclick="addNewTag()">
                            <i class="fas fa-plus me-2"></i>
                            添加数据点
                        </button>
                    </div>
                </div>

                <!-- 操作按钮 -->
                <div class="d-flex gap-3 mt-4">
                    <button type="button" class="btn btn-primary btn-lg" onclick="saveDeviceConfig()">
                        <i class="fas fa-save me-2"></i>
                        保存配置
                    </button>
                    <button type="button" class="btn btn-success btn-lg" onclick="deployConfig()">
                        <i class="fas fa-rocket me-2"></i>
                        部署设备
                    </button>
                    <button type="button" class="btn btn-secondary btn-lg" onclick="resetForm()">
                        <i class="fas fa-undo me-2"></i>
                        重置表单
                    </button>
                </div>
            </div>

            <!-- 右侧预览和帮助 -->
            <div class="col-lg-4">
                <!-- 配置预览 -->
                <div class="card mb-4">
                    <div class="card-header bg-info text-white">
                        <h6 class="mb-0">
                            <i class="fas fa-eye me-2"></i>
                            配置预览
                        </h6>
                    </div>
                    <div class="card-body p-0">
                        <div class="config-preview" id="configPreview">
                            请填写设备配置信息...
                        </div>
                    </div>
                </div>

                <!-- 帮助信息 -->
                <div class="card">
                    <div class="card-header bg-warning">
                        <h6 class="mb-0">
                            <i class="fas fa-question-circle me-2"></i>
                            配置帮助
                        </h6>
                    </div>
                    <div class="card-body">
                        <div id="protocolHelp">
                            <h6>配置说明:</h6>
                            <ul class="list-unstyled">
                                <li><i class="fas fa-check text-success me-2"></i>填写设备基本信息</li>
                                <li><i class="fas fa-check text-success me-2"></i>选择通讯协议类型</li>
                                <li><i class="fas fa-check text-success me-2"></i>配置连接参数</li>
                                <li><i class="fas fa-check text-success me-2"></i>测试设备连接</li>
                                <li><i class="fas fa-check text-success me-2"></i>添加数据点配置</li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        let currentTags = [];
        
        // 安全转义函数
        function escapeHtml(unsafe) {
            if (typeof unsafe !== 'string') {
                unsafe = String(unsafe || '');
            }
            return unsafe
                .replace(/&/g, "&amp;")
                .replace(/</g, "&lt;")
                .replace(/>/g, "&gt;")
                .replace(/"/g, "&quot;")
                .replace(/'/g, "&#39;");
        }
        
        function escapeJs(unsafe) {
            if (typeof unsafe !== 'string') {
                unsafe = String(unsafe || '');
            }
            return unsafe
                .replace(/\\/g, "\\\\")
                .replace(/'/g, "\\'")
                .replace(/"/g, '\\"')
                .replace(/\n/g, "\\n")
                .replace(/\r/g, "\\r")
                .replace(/\t/g, "\\t");
        }
        
        // 更新协议配置表单
        function updateProtocolForm() {
            const protocol = document.getElementById('protocolType').value;
            
            // 隐藏所有协议配置
            document.querySelectorAll('.protocol-config').forEach(el => {
                el.style.display = 'none';
            });
            
            // 显示选中的协议配置
            if (protocol) {
                const configDiv = document.getElementById(protocol + 'Config');
                if (configDiv) {
                    configDiv.style.display = 'block';
                }
            }
            
            // 更新表头文字
            updateTableHeader(protocol);
            
            // 重新渲染数据点表格以适应新协议
            renderTagsTable();
            
            // 更新表头文字
            updateTableHeader(protocol);
            
            // 重新渲染数据点表格以适应新协议
            renderTagsTable();
            
            updateConfigPreview();
            updateProtocolHelp(protocol);
        }
        
        // 更新表头文字
        function updateTableHeader(protocol) {
            const headerMap = {
                'modbus': '寄存器地址',
                's7': 'S7地址',
                'opcua': '节点ID',
                'mqtt': '主题'
            };
            
            const headerElement = document.getElementById('addressHeader');
            if (headerElement) {
                headerElement.textContent = headerMap[protocol] || '地址/节点ID';
            }
        }
        
        // 更新表头文字
        function updateTableHeader(protocol) {
            const headerMap = {
                'modbus': '寄存器地址',
                's7': 'S7地址',
                'opcua': '节点ID',
                'mqtt': '主题'
            };
            
            const headerElement = document.getElementById('addressHeader');
            if (headerElement) {
                headerElement.textContent = headerMap[protocol] || '地址/节点ID';
            }
        }
        
        // 更新协议帮助信息
        function updateProtocolHelp(protocol) {
            const helpContent = {
                'modbus': `
                    <h6>Modbus 配置说明:</h6>
                    <ul class="small">
                        <li>IP地址: PLC设备的IP地址</li>
                        <li>端口: 通常为502</li>
                        <li>从站ID: 设备的从站地址</li>
                        <li>地址格式: 40001表示保持寄存器1</li>
                    </ul>
                `,
                's7': `
                    <h6>S7 配置说明:</h6>
                    <ul class="small">
                        <li>IP地址: 西门子PLC的IP地址</li>
                        <li>机架号: 通常为0</li>
                        <li>插槽号: CPU插槽号，通常为1</li>
                        <li>地址格式: DB1.DBD10表示DB1第10字节的双字</li>
                    </ul>
                `,
                'opcua': `
                    <h6>OPC UA 配置说明:</h6>
                    <ul class="small">
                        <li>端点: 服务器的完整URL</li>
                        <li>安全策略: 根据服务器要求选择</li>
                        <li>认证: 如果服务器需要认证</li>
                        <li>节点ID: ns=2;i=1001 格式</li>
                    </ul>
                `,
                'mqtt': `
                    <h6>MQTT 配置说明:</h6>
                    <ul class="small">
                        <li>Broker: MQTT消息代理地址</li>
                        <li>端口: 通常为1883</li>
                        <li>主题: 要订阅的数据主题</li>
                        <li>认证: 如果Broker需要认证</li>
                    </ul>
                `
            };
            
            document.getElementById('protocolHelp').innerHTML = helpContent[protocol] || 
                '<h6>配置说明:</h6><p class="small text-muted">请先选择协议类型</p>';
        }
        
        // 添加新数据点
        function addNewTag() {
            const protocol = document.getElementById('protocolType').value;
            if (!protocol) {
                alert('请先选择协议类型');
                return;
            }
            
            const newTag = {
                id: Date.now(),
                name: '',
                address: '',
                node_id: '',  // 添加OPC UA节点ID字段
                topic: '',    // 添加MQTT主题字段
                dataType: 'float',
                access: 'R',
                description: ''
            };
            
            currentTags.push(newTag);
            renderTagsTable();
        }
        
        // 渲染数据点表格
        function renderTagsTable() {
            const tbody = document.getElementById('tagsTableBody');
            
            if (currentTags.length === 0) {
                tbody.innerHTML = `
                    <tr>
                        <td colspan="6" class="text-center text-muted py-4">
                            <i class="fas fa-database fa-2x mb-2"></i>
                            <p class="mb-0">暂无数据点配置</p>
                            <small>点击"添加数据点"开始配置</small>
                        </td>
                    </tr>
                `;
                return;
            }
            
            const protocol = document.getElementById('protocolType').value;
            
            tbody.innerHTML = currentTags.map(tag => {
                let addressField = '';
                if (protocol === 'opcua') {
                    addressField = `
                        <div class="input-group input-group-sm">
                            <input type="text" class="form-control" 
                                   value="${escapeHtml(tag.node_id || '')}" 
                               onchange="updateTag(${tag.id}, 'node_id', this.value)"
                                   placeholder="ns=2;s=节点路径" id="nodeId_${tag.id}">
                            <button class="btn btn-outline-secondary" type="button" 
                                    onclick="selectOpcuaNode(${tag.id})" title="选择节点">
                                <i class="fas fa-search"></i>
                            </button>
                        </div>
                    `;
                } else if (protocol === 'mqtt') {
                    addressField = `
                        <input type="text" class="form-control form-control-sm" 
                               value="${escapeHtml(tag.topic || '')}" 
                               onchange="updateTag(${tag.id}, 'topic', this.value)"
                               placeholder="sensor/temperature">
                    `;
                } else {
                    addressField = `
                        <input type="text" class="form-control form-control-sm" 
                               value="${escapeHtml(tag.address || '')}" 
                               onchange="updateTag(${tag.id}, 'address', this.value)"
                               placeholder="40001">
                    `;
                }
                
                return `
                <tr>
                    <td>
                        <input type="text" class="form-control form-control-sm" 
                               value="${escapeHtml(tag.name || '')}" 
                               onchange="updateTag(${tag.id}, 'name', this.value)"
                               placeholder="tag_name">
                    </td>
                    <td>
                        ${addressField}
                        ${protocol === 'opcua' ? '<small class="text-muted">格式: ns=2;s=节点路径</small>' : ''}
                    </td>
                    <td>
                        <select class="form-select form-select-sm" 
                                onchange="updateTag(${tag.id}, 'dataType', this.value)">
                            <option value="bool" ${tag.dataType === 'bool' ? 'selected' : ''}>布尔</option>
                            <option value="int16" ${tag.dataType === 'int16' ? 'selected' : ''}>16位整数</option>
                            <option value="int32" ${tag.dataType === 'int32' ? 'selected' : ''}>32位整数</option>
                            <option value="float" ${tag.dataType === 'float' ? 'selected' : ''}>浮点数</option>
                            <option value="double" ${tag.dataType === 'double' ? 'selected' : ''}>双精度</option>
                            <option value="string" ${tag.dataType === 'string' ? 'selected' : ''}>字符串</option>
                        </select>
                    </td>
                    <td>
                        <select class="form-select form-select-sm" 
                                onchange="updateTag(${tag.id}, 'access', this.value)">
                            <option value="R" ${tag.access === 'R' ? 'selected' : ''}>只读</option>
                            <option value="W" ${tag.access === 'W' ? 'selected' : ''}>只写</option>
                            <option value="RW" ${tag.access === 'RW' ? 'selected' : ''}>读写</option>
                        </select>
                    </td>
                    <td>
                        <input type="text" class="form-control form-control-sm" 
                               value="${escapeHtml(tag.description || '')}" 
                               onchange="updateTag(${tag.id}, 'description', this.value)"
                               placeholder="描述信息">
                    </td>
                    <td>
                        <input type="text" class="form-control form-control-sm" 
                               value="${escapeHtml(tag.unit || '')}" 
                               onchange="updateTag(${tag.id}, 'unit', this.value)"
                               placeholder="单位">
                    </td>
                    <td>
                        <button type="button" class="btn btn-remove-tag btn-sm" 
                                onclick="removeTag(${tag.id})" title="删除">
                            <i class="fas fa-times"></i>
                        </button>
                    </td>
                </tr>
                `;
            }).join('');
        }
        
        // 更新数据点
        function updateTag(id, field, value) {
            const tag = currentTags.find(t => t.id === id);
            if (tag) {
                tag[field] = value;
                console.log(`更新数据点 ${id}:`, field, '=', value, '完整标签:', tag);
                updateConfigPreview();
            }
        }
        
        // 删除数据点
        function removeTag(id) {
            currentTags = currentTags.filter(t => t.id !== id);
            renderTagsTable();
            updateConfigPreview();
        }
        
        // 更新配置预览
        function updateConfigPreview() {
            const config = generateConfig();
            document.getElementById('configPreview').textContent = JSON.stringify(config, null, 2);
        }
        
        // 生成配置对象
        function generateConfig() {
            const protocol = document.getElementById('protocolType').value;
            const config = {
                name: document.getElementById('deviceName').value || 'NewDevice',
                description: document.getElementById('deviceDescription').value || '',
                type: protocol,
                enabled: true,
                polling_interval: parseInt(document.getElementById('pollingInterval').value) || 1000,
                config: {},
                points: currentTags.filter(tag => {
                    // 根据协议类型检查必要字段
                    if (!tag.name) return false;
                    if (protocol === 'opcua') {
                        return tag.node_id && tag.node_id.trim() !== '';
                    } else if (protocol === 'mqtt') {
                        return tag.topic && tag.topic.trim() !== '';
                    } else {
                        return tag.address && tag.address.trim() !== '';
                    }
                })
            };
            
            // 根据协议类型填充连接配置
            switch (protocol) {
                case 'modbus':
                    config.config = {
                        ip: document.getElementById('modbusHost').value,
                        port: parseInt(document.getElementById('modbusPort').value) || 502,
                        unit_id: parseInt(document.getElementById('modbusSlaveId').value) || 1,
                        timeout: parseInt(document.getElementById('modbusTimeout').value) || 3,
                        retries: parseInt(document.getElementById('modbusRetries').value) || 3
                    };
                    break;
                case 's7':
                    config.config = {
                        ip: document.getElementById('s7Host').value,
                        rack: parseInt(document.getElementById('s7Rack').value) || 0,
                        slot: parseInt(document.getElementById('s7Slot').value) || 1
                    };
                    break;
                case 'opcua':
                    config.config = {
                        endpoint: document.getElementById('opcuaEndpoint').value,
                        security_policy: document.getElementById('opcuaSecurity').value,
                        username: document.getElementById('opcuaUsername').value,
                        password: document.getElementById('opcuaPassword').value
                    };
                    break;
                case 'mqtt':
                    config.config = {
                        broker: document.getElementById('mqttHost').value,
                        port: parseInt(document.getElementById('mqttPort').value) || 1883,
                        client_id: document.getElementById('mqttClientId').value,
                        username: document.getElementById('mqttUsername').value,
                        password: document.getElementById('mqttPassword').value,
                        topics: document.getElementById('mqttTopics').value.split('\n').filter(t => t.trim())
                    };
                    break;
            }
            
            return config;
        }
        
        // 测试连接
        async function testConnection() {
            const config = generateConfig();
            const statusDiv = document.getElementById('connectionStatus');
            
            statusDiv.innerHTML = '<span class="text-info"><i class="fas fa-spinner fa-spin me-2"></i>正在测试连接...</span>';
            
            try {
                const response = await fetch('/api/device/test-connection', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(config)
                });
                
                const result = await response.json();
                
                if (result.success) {
                    statusDiv.innerHTML = '<span class="text-success"><i class="fas fa-check-circle me-2"></i>连接成功</span>';
                } else {
                    statusDiv.innerHTML = `<span class="text-danger"><i class="fas fa-exclamation-circle me-2"></i>连接失败: ${result.message}</span>`;
                }
            } catch (error) {
                statusDiv.innerHTML = `<span class="text-danger"><i class="fas fa-exclamation-circle me-2"></i>测试失败: ${error.message}</span>`;
            }
        }
        
        // 验证配置
        function validateConfig(config) {
            const errors = [];
            
            // 基本验证
            if (!config.name) {
                errors.push('设备名称不能为空');
            }
            
            if (!config.type) {
                errors.push('请选择协议类型');
            }
            
            // 协议特定验证
            if (config.type === 'modbus') {
                if (!config.config.ip) {
                    errors.push('Modbus配置缺少IP地址');
                }
            } else if (config.type === 's7') {
                if (!config.config.ip) {
                    errors.push('S7配置缺少IP地址');
                }
            } else if (config.type === 'opcua') {
                if (!config.config.endpoint) {
                    errors.push('OPC UA配置缺少端点URL');
                }
            } else if (config.type === 'mqtt') {
                if (!config.config.broker) {
                    errors.push('MQTT配置缺少Broker地址');
                }
            }
            
            // 数据点验证
            if (config.points && config.points.length > 0) {
                config.points.forEach((point, index) => {
                    if (!point.name) {
                        errors.push(`数据点 ${index + 1}: 名称不能为空`);
                    }
                    if (config.type === 'opcua' && !point.node_id) {
                        errors.push(`数据点 '${point.name}': OPC UA点缺少节点ID`);
                    } else if (config.type === 'mqtt' && !point.topic) {
                        errors.push(`数据点 '${point.name}': MQTT点缺少主题`);
                    } else if (['modbus', 's7'].includes(config.type) && !point.address) {
                        errors.push(`数据点 '${point.name}': 缺少地址`);
                    }
                });
            }
            
            return errors;
        }
        
        // 保存设备配置
        async function saveDeviceConfig() {
            const config = generateConfig();
            
            // 添加调试信息
            console.log('=== 保存设备配置 ===');
            console.log('生成的配置:', JSON.stringify(config, null, 2));
            console.log('当前数据点列表:', currentTags);
            console.log('数据点过滤结果:', config.points);
            
            // 前端验证
            const validationErrors = validateConfig(config);
            if (validationErrors.length > 0) {
                console.error('前端验证失败:', validationErrors);
                alert('配置验证失败:\n' + validationErrors.join('\n'));
                return;
            }
            
            try {
                console.log('发送到服务器的数据:', JSON.stringify(config, null, 2));
                
                const response = await fetch('/api/device/config', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(config)
                });
                
                const result = await response.json();
                console.log('服务器响应:', result);
                
                if (result.success) {
                    alert('设备配置保存成功！');
                    // 可选：清空表单或跳转到设备管理页面
                } else {
                    const errorMessage = result.error;
                    const errorDetails = result.details ? '\n详细信息:\n' + result.details.join('\n') : '';
                    console.error('服务器验证失败:', result);
                    alert(`保存失败: ${errorMessage}${errorDetails}`);
                }
            } catch (error) {
                console.error('请求异常:', error);
                alert(`保存失败: ${error.message}`);
            }
        }
        
        // 部署设备
        async function deployConfig() {
            const config = generateConfig();
            
            if (!config.name || !config.type) {
                alert('请先保存设备配置');
                return;
            }
            
            try {
                const response = await fetch(`/api/device/${config.name}/deploy`, {
                    method: 'POST'
                });
                
                const result = await response.json();
                
                if (result.success) {
                    alert('设备部署成功！设备已开始采集数据。');
                } else {
                    alert(`部署失败: ${result.message}`);
                }
            } catch (error) {
                alert(`部署失败: ${error.message}`);
            }
        }
        
        // 重置表单
        function resetForm() {
            if (confirm('确定要重置表单？所有未保存的配置将丢失。')) {
                document.getElementById('deviceConfigForm').reset();
                currentTags = [];
                renderTagsTable();
                updateProtocolForm();
            }
        }
        
        // OPC UA节点浏览功能
        let opcuaNodes = []; // 存储浏览到的节点
        let nodeSelectionModal = null; // 节点选择模态框
        let currentSelectingTagId = null; // 当前正在选择节点的标签ID
        
        // 浏览OPC UA节点
        async function browseOpcuaNodes() {
            const endpoint = document.getElementById('opcuaEndpoint').value;
            const security_policy = document.getElementById('opcuaSecurity').value;
            const username = document.getElementById('opcuaUsername').value;
            const password = document.getElementById('opcuaPassword').value;
            
            if (!endpoint) {
                alert('请先填写OPC UA服务器端点');
                return;
            }
            
            const statusDiv = document.getElementById('opcuaBrowsingStatus');
            statusDiv.innerHTML = '<span class="text-info"><i class="fas fa-spinner fa-spin me-2"></i>正在浏览节点...</span>';
            
            try {
                const response = await fetch('/api/opcua/browse-nodes', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        endpoint: endpoint,
                        security_policy: security_policy,
                        username: username,
                        password: password
                    })
                });
                
                if (!response.ok) {
                    throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
                }
                
                const result = await response.json();
                
                if (result.success) {
                    opcuaNodes = result.data.nodes;
                    statusDiv.innerHTML = `<span class="text-success"><i class="fas fa-check-circle me-2"></i>浏览成功，找到 ${result.data.total_nodes} 个节点</span>`;
                    showNodeSelectionModal();
                } else {
                    statusDiv.innerHTML = `<span class="text-danger"><i class="fas fa-exclamation-circle me-2"></i>浏览失败: ${escapeHtml(result.error || '未知错误')}</span>`;
                }
            } catch (error) {
                let errorMessage = '连接失败';
                if (error.message) {
                    errorMessage = error.message;
                }
                statusDiv.innerHTML = `<span class="text-danger"><i class="fas fa-exclamation-circle me-2"></i>浏览失败: ${escapeHtml(errorMessage)}</span>`;
                console.error('OPC UA节点浏览失败:', error);
            }
        }
        
        // 为特定标签选择OPC UA节点
        function selectOpcuaNode(tagId) {
            if (!opcuaNodes || opcuaNodes.length === 0) {
                alert('请先浏览服务器节点');
                return;
            }
            
            currentSelectingTagId = tagId;
            showNodeSelectionModal();
        }
        
        // 显示节点选择模态框
        function showNodeSelectionModal() {
            // 创建模态框HTML
            const modalHtml = `
                <div class="modal fade" id="nodeSelectionModal" tabindex="-1" aria-labelledby="nodeSelectionModalLabel" aria-hidden="true">
                    <div class="modal-dialog modal-xl">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title" id="nodeSelectionModalLabel">
                                    <i class="fas fa-sitemap me-2"></i>
                                    选择OPC UA节点
                                </h5>
                                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="关闭"></button>
                            </div>
                            <div class="modal-body">
                                <div class="alert alert-info alert-sm mb-3">
                                    <i class="fas fa-info-circle me-2"></i>
                                    <strong>使用说明：</strong> 点击变量节点进行选择，按住 <kbd>Ctrl</kbd> 键可多选节点
                                </div>
                                <div class="row">
                                    <div class="col-md-6">
                                        <h6>节点树</h6>
                                        <div id="nodeTree" style="max-height: 500px; overflow-y: auto; border: 1px solid #dee2e6; padding: 10px; border-radius: 5px;">
                                            ${renderNodeTree(opcuaNodes)}
                                        </div>
                                    </div>
                                    <div class="col-md-6">
                                        <h6>节点详情</h6>
                                        <div id="nodeDetails" style="max-height: 500px; overflow-y: auto; border: 1px solid #dee2e6; padding: 10px; border-radius: 5px; background-color: #f8f9fa;">
                                            <p class="text-muted">请从左侧选择一个节点查看详情</p>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-secondary" onclick="closeNodeSelectionModal()">取消</button>
                                <button type="button" class="btn btn-primary" onclick="confirmNodeSelection()" disabled id="confirmSelectBtn">确认选择</button>
                            </div>
                        </div>
                    </div>
                </div>
            `;
            
            // 移除已存在的模态框
            const existingModal = document.getElementById('nodeSelectionModal');
            if (existingModal) {
                existingModal.remove();
            }
            
            // 添加新模态框到页面
            document.body.insertAdjacentHTML('beforeend', modalHtml);
            
            // 显示模态框
            nodeSelectionModal = new bootstrap.Modal(document.getElementById('nodeSelectionModal'));
            nodeSelectionModal.show();
        }
        
        // 渲染节点树
        function renderNodeTree(nodes, level = 0) {
            return nodes.map(node => {
                const indent = '&nbsp;'.repeat(level * 4);
                const hasChildren = node.children && node.children.length > 0;
                const isVariable = node.is_variable;
                const icon = isVariable ? 'fa-database' : (hasChildren ? 'fa-folder' : 'fa-file');
                const nodeClass = isVariable ? 'variable-node' : 'folder-node';
                
                let html = `
                    <div class="node-item ${nodeClass}" style="margin-bottom: 2px;">
                        <span style="padding-left: ${level * 20}px;">
                            ${hasChildren ? `<i class="fas fa-chevron-right toggle-icon me-1" onclick="toggleNodeChildren(this)" style="cursor: pointer;"></i>` : '<span style="width: 16px; display: inline-block;"></span>'}
                            <i class="fas ${icon} me-2 ${isVariable ? 'text-primary' : 'text-muted'}"></i>
                            <span class="node-name" onclick="selectNode('${escapeJs(node.node_id)}', '${escapeJs(node.display_name)}', ${isVariable}, event)" 
                                  style="cursor: pointer; color: ${isVariable ? '#0066cc' : '#666'};"
                                  title="${escapeHtml(node.node_id)}">
                                ${escapeHtml(node.display_name)}
                            </span>
                            ${isVariable ? '<span class="badge bg-success ms-2">变量</span>' : ''}
                        </span>
                    </div>
                `;
                
                if (hasChildren) {
                    html += `<div class="node-children" style="display: none;">${renderNodeTree(node.children, level + 1)}</div>`;
                }
                
                return html;
            }).join('');
        }
        
        // 切换节点子项显示/隐藏
        function toggleNodeChildren(toggleIcon) {
            const nodeItem = toggleIcon.closest('.node-item');
            const childrenDiv = nodeItem.nextElementSibling;
            
            if (childrenDiv && childrenDiv.classList.contains('node-children')) {
                if (childrenDiv.style.display === 'none') {
                    childrenDiv.style.display = 'block';
                    toggleIcon.classList.remove('fa-chevron-right');
                    toggleIcon.classList.add('fa-chevron-down');
                } else {
                    childrenDiv.style.display = 'none';
                    toggleIcon.classList.remove('fa-chevron-down');
                    toggleIcon.classList.add('fa-chevron-right');
                }
            }
        }
        
        let selectedNodeId = null;
        let selectedNodeName = null;
        let selectedNodes = []; // 支持多选
        
        // 选择节点
        function selectNode(nodeId, displayName, isVariable, event) {
            // 仅允许选择变量节点
            if (!isVariable) {
                return;
            }
            
            // 检查是否按住Ctrl键进行多选
            const isMultiSelect = event && (event.ctrlKey || event.metaKey);
            
            if (isMultiSelect) {
                // 多选模式
                const existingIndex = selectedNodes.findIndex(node => node.nodeId === nodeId);
                
                if (existingIndex >= 0) {
                    // 取消选择
                    selectedNodes.splice(existingIndex, 1);
                    event.target.style.backgroundColor = '';
                    event.target.style.color = '#0066cc';
                } else {
                    // 添加到选择列表
                    selectedNodes.push({
                        nodeId: nodeId,
                        displayName: displayName
                    });
                    event.target.style.backgroundColor = '#007bff';
                    event.target.style.color = 'white';
                }
                
                // 更新单选变量（使用最后选择的节点）
                if (selectedNodes.length > 0) {
                    const lastSelected = selectedNodes[selectedNodes.length - 1];
                    selectedNodeId = lastSelected.nodeId;
                    selectedNodeName = lastSelected.displayName;
                } else {
                                    selectedNodeId = null;
                selectedNodeName = null;
                selectedNodes = [];
                }
            } else {
                // 单选模式
                selectedNodes = [{
                    nodeId: nodeId,
                    displayName: displayName
                }];
                selectedNodeId = nodeId;
                selectedNodeName = displayName;
                
                // 更新选中状态
                document.querySelectorAll('.node-name').forEach(node => {
                    node.style.backgroundColor = '';
                    node.style.color = node.closest('.variable-node') ? '#0066cc' : '#666';
                });
                
                event.target.style.backgroundColor = '#007bff';
                event.target.style.color = 'white';
            }
            
            // 启用确认按钮
            document.getElementById('confirmSelectBtn').disabled = selectedNodes.length === 0;
            
            // 更新确认按钮文本
            const confirmBtn = document.getElementById('confirmSelectBtn');
            if (selectedNodes.length > 1) {
                confirmBtn.textContent = `确认选择 (${selectedNodes.length}个节点)`;
            } else {
                confirmBtn.textContent = '确认选择';
            }
            
            // 显示节点详情
            if (selectedNodes.length === 1) {
                showNodeDetails(nodeId, displayName);
            } else if (selectedNodes.length > 1) {
                showMultiNodeDetails();
            }
        }
        
        // 显示节点详情
        function showNodeDetails(nodeId, displayName) {
            const node = findNodeById(opcuaNodes, nodeId);
            if (!node) return;
            
            const detailsHtml = `
                <h6>节点信息</h6>
                <table class="table table-sm">
                    <tr><td><strong>显示名称:</strong></td><td>${escapeHtml(node.display_name)}</td></tr>
                    <tr><td><strong>浏览名称:</strong></td><td>${escapeHtml(node.browse_name)}</td></tr>
                    <tr><td><strong>节点ID:</strong></td><td><code>${escapeHtml(node.node_id)}</code></td></tr>
                    <tr><td><strong>数据类型:</strong></td><td>${escapeHtml(node.data_type)}</td></tr>
                    <tr><td><strong>是否为变量:</strong></td><td>${node.is_variable ? '是' : '否'}</td></tr>
                    ${node.current_value ? `<tr><td><strong>当前值:</strong></td><td>${escapeHtml(String(node.current_value))}</td></tr>` : ''}
                </table>
                <div class="mt-3">
                    <h6>配置预览</h6>
                    <pre style="background: #f8f9fa; padding: 10px; border-radius: 5px; font-size: 12px;">{
  "name": "${escapeJs(displayName)}",
  "description": "${escapeJs(displayName)}",
  "data_type": "float",
  "access": "R", 
  "unit": "",
  "node_id": "${escapeJs(nodeId)}"
}</pre>
                </div>
            `;
            
            document.getElementById('nodeDetails').innerHTML = detailsHtml;
        }
        
        // 显示多节点详情
        function showMultiNodeDetails() {
            const detailsHtml = `
                <h6>已选择 ${selectedNodes.length} 个节点</h6>
                <div style="max-height: 300px; overflow-y: auto;">
                    ${selectedNodes.map((selected, index) => {
                        const node = findNodeById(opcuaNodes, selected.nodeId);
                        if (!node) return '';
                        
                        return `
                            <div class="card mb-2">
                                <div class="card-body p-2">
                                    <h6 class="card-title mb-1">${index + 1}. ${escapeHtml(node.display_name)}</h6>
                                    <p class="card-text small mb-1">
                                        <strong>节点ID:</strong> <code>${escapeHtml(node.node_id)}</code><br>
                                        <strong>数据类型:</strong> ${escapeHtml(node.data_type)}<br>
                                        ${node.current_value ? `<strong>当前值:</strong> ${escapeHtml(String(node.current_value))}` : ''}
                                    </p>
                                </div>
                            </div>
                        `;
                    }).join('')}
                </div>
                <div class="mt-3">
                    <h6>批量配置预览</h6>
                    <p class="small text-muted">将为每个选中的节点创建一个数据点配置</p>
                </div>
            `;
            
            document.getElementById('nodeDetails').innerHTML = detailsHtml;
        }
        
        // 递归查找节点
        function findNodeById(nodes, nodeId) {
            for (let node of nodes) {
                if (node.node_id === nodeId) {
                    return node;
                }
                if (node.children) {
                    const found = findNodeById(node.children, nodeId);
                    if (found) return found;
                }
            }
            return null;
        }
        
        // 确认节点选择
        function confirmNodeSelection() {
            if (selectedNodes.length === 0) {
                alert('请选择至少一个节点');
                return;
            }
            
            console.log('确认选择节点:', selectedNodes);
            console.log('当前选择的标签ID:', currentSelectingTagId);
            
            if (currentSelectingTagId && selectedNodes.length === 1) {
                // 为特定标签设置节点ID（仅单选时）
                const selected = selectedNodes[0];
                const nodeIdInput = document.getElementById(`nodeId_${currentSelectingTagId}`);
                console.log('找到的输入框:', nodeIdInput);
                
                if (nodeIdInput) {
                    nodeIdInput.value = selected.nodeId;
                    updateTag(currentSelectingTagId, 'node_id', selected.nodeId);
                    
                    // 自动填充标签名称和描述
                    const tag = currentTags.find(t => t.id === currentSelectingTagId);
                    if (tag) {
                        if (!tag.name || tag.name.trim() === '') {
                            tag.name = selected.displayName;
                        }
                        if (!tag.description || tag.description.trim() === '') {
                            tag.description = selected.displayName;
                        }
                        console.log('更新后的标签:', tag);
                        renderTagsTable();
                        updateConfigPreview();
                    }
                }
                currentSelectingTagId = null;
            } else {
                // 批量创建数据点
                selectedNodes.forEach((selected, index) => {
                    const newTag = {
                        id: Date.now() + index, // 确保唯一ID
                        name: selected.displayName,
                        node_id: selected.nodeId,
                        dataType: 'float',
                        access: 'R',
                        description: selected.displayName,
                        unit: ''
                    };
                    
                    currentTags.push(newTag);
                    console.log('创建新标签:', newTag);
                });
                
                renderTagsTable();
                updateConfigPreview();
                currentSelectingTagId = null;
            }
            
            // 安全关闭模态框
            closeNodeSelectionModal();
        }
        
        // 安全关闭模态框的函数
        function closeNodeSelectionModal() {
            try {
                if (nodeSelectionModal) {
                    // 移除焦点以避免aria-hidden问题
                    const activeElement = document.activeElement;
                    if (activeElement && activeElement.closest('#nodeSelectionModal')) {
                        activeElement.blur();
                    }
                    
                    // 关闭模态框
                    nodeSelectionModal.hide();
                    
                    // 清理状态
                    selectedNodeId = null;
                    selectedNodeName = null;
                    selectedNodes = [];
                    
                    // 延迟移除模态框元素，避免焦点问题
                    setTimeout(() => {
                        const modal = document.getElementById('nodeSelectionModal');
                        if (modal) {
                            modal.remove();
                        }
                    }, 300);
                }
            } catch (error) {
                console.warn('关闭模态框时出现错误:', error);
                // 强制移除模态框
                const modal = document.getElementById('nodeSelectionModal');
                if (modal) {
                    modal.remove();
                }
                selectedNodeId = null;
                selectedNodeName = null;
            }
        }
        
        // 页面加载时初始化
        document.addEventListener('DOMContentLoaded', function() {
            renderTagsTable();
            updateConfigPreview();
            
            // 添加表单变化监听
            document.getElementById('deviceConfigForm').addEventListener('input', updateConfigPreview);
            
            // 添加全局错误处理（过滤掉浏览器扩展相关错误）
            window.addEventListener('error', function(e) {
                if (e.message && e.message.includes('runtime.lastError')) {
                    // 忽略浏览器扩展相关的错误
                    return;
                }
                console.warn('页面错误:', e.error);
            });
            
            // 添加未处理的Promise拒绝处理
            window.addEventListener('unhandledrejection', function(e) {
                if (e.reason && e.reason.toString().includes('runtime.lastError')) {
                    // 忽略浏览器扩展相关的错误
                    e.preventDefault();
                    return;
                }
                console.warn('未处理的Promise拒绝:', e.reason);
            });
            
            // 添加控制台说明，帮助用户理解runtime.lastError
            console.info('%c注意：如果看到 "runtime.lastError" 错误，这通常是浏览器扩展引起的，不影响页面功能。', 'color: blue; font-weight: bold;');
        });
    </script>
</body>
</html> 